/*
 * INSANE - Interactive Structural Analysis Environment
 *
 * Copyright (C) 2003-2004
 * Universidade Federal de Minas Gerais
 * Escola de Engenharia
 * Departamento de Engenharia de Estruturas
 *
 * Author's email :     insane@dees.ufmg.br
 * Author's Website :   http://www.dees.ufmg.br/insane
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-
 * 1307, USA.
 *
 */

package br.ufmg.dees.insane.ui.rich.postp.postp_view;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Observable;
import java.util.Observer;

import javax.swing.BorderFactory;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.WindowConstants;
import javax.swing.event.InternalFrameEvent;
import javax.swing.event.InternalFrameListener;
import javax.swing.plaf.FontUIResource;

import br.ufmg.dees.insane.commons.InsaneProperties;
import br.ufmg.dees.insane.commons.command.Command;
import br.ufmg.dees.insane.commons.command.CommandHolder;
import br.ufmg.dees.insane.commons.view.IView;
import br.ufmg.dees.insane.commons.view.ViewState;
import br.ufmg.dees.insane.model.postp.PostpModel;
import br.ufmg.dees.insane.model.postp.StepPostp;
import br.ufmg.dees.insane.parser.FemModelToPostpModel;
import br.ufmg.dees.insane.parser.ParserHalfEdge;
import br.ufmg.dees.insane.ui.rich.postp.postp_controller.PostpController;
import br.ufmg.dees.insane.ui.rich.postp.postp_view.command.PopUpCommand;
import br.ufmg.dees.insane.ui.rich.postp.postp_view.command.SelectCommand;

/**
 * @author Penna,S.S. & Pitangueira, Roque
 *
 */
public class InterfacePostp extends JInternalFrame implements ActionListener, Observer {
	
	/**
	 * Comment for <code>serialVersionUID</code>
	 */
	private static final long serialVersionUID = 1L;
	
	private PostpView view = new PostpView(this);
	private InsaneProperties properties = new InsaneProperties();
	private ParserHalfEdge parser;
	private ArrayList halfEdgeModelList;
	private PostpModel postpModel;
	private StepPostp stepPostp;
	private DesktopPostp desktop;
	private JPanel drawArea = new JPanel();
	private NumberFormat numberFormat;
	
//	*****************************************************************************
	
	/**
	 * The constructor method. <br>
	 * Calls the init() method throwing an exception.
	 */
	public InterfacePostp() {
		try {
			setUpFormat();
			init();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
//	*****************************************************************************
	
	/**
	 *  It's called by the constructor. <br>
	 *  Sets Panels, components and provides a window listener.
	 */
	private void init() throws Exception {
		this.setTitle("INSANE POSTP " + this.getProperties().getVersion());
		this.setFonts();
		this.setSize(new Dimension(800,640));
		this.setMaximizable(true);
		this.setClosable(true);
		
		this.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
		
		this.getContentPane().setLayout(new BorderLayout());
		
		drawArea.setLayout(new BorderLayout());
		drawArea.setBorder(BorderFactory.createEmptyBorder(0,0,0,3));
		
		this.getView().getDrawingArea().setSize(this.getSize());
		this.getView().getDrawingArea().setPreferredSize(this.getSize());
		this.getView().getDrawingArea().setMaximumSize(this.getSize());
		this.getView().getDrawingArea().setMinimumSize(this.getSize());
		this.getView().getDrawingArea().setSize(this.getSize());
		
		drawArea.add(this.getView().getDrawingArea(), BorderLayout.CENTER);
		
		this.getContentPane().add(drawArea, BorderLayout.CENTER);
		
		this.addInternalFrameListener(new IntFrameListner());
		
		this.setInitialInterface();
		
	}
	
	/** Add Component Without a Layout Manager (Absolute Positioning) */ 
	@SuppressWarnings("unused")
	private void addComponent(Container container,Component c,int x,int y,int width,int height) { 
		c.setBounds(x,y,width,height); 
		container.add(c); 
	}   
	
//	******************************************************************************
	public void setFonts() {
		try {
			UIManager.setLookAndFeel(UIManager.getInstalledLookAndFeels()[0].getClassName());
			
			Font fontCurrent = UIManager.getFont("Button.font");
			fontCurrent = UIManager.getFont("Arial");
			String name = fontCurrent.getName();
			
			//Creates similar font with the specified style and size
			FontUIResource fontResourceNew  = new FontUIResource(name, Font.PLAIN, 12);
			
			//Sets all items fonts
			UIManager.put("Button.font", fontResourceNew);
			UIManager.put("CheckBox.font", fontResourceNew);
			UIManager.put("CheckBoxMenuItem.font", fontResourceNew);
			UIManager.put("ColorChooser.font", fontResourceNew);
			UIManager.put("ComboBox.font", fontResourceNew);
			UIManager.put("DesktopIcon.font", fontResourceNew);
			UIManager.put("EditorPane.font", fontResourceNew);
			UIManager.put("InternalFrame.font", fontResourceNew);
			UIManager.put("Label.font", fontResourceNew);
			UIManager.put("List.font", fontResourceNew);
			UIManager.put("MenuBar.font", fontResourceNew);
			UIManager.put("Menu.font", fontResourceNew);
			UIManager.put("MenuItem.font", fontResourceNew);
			UIManager.put("OptionPane.font", fontResourceNew);
			UIManager.put("PasswordField.font", fontResourceNew);
			UIManager.put("PopupMenu.font", fontResourceNew);
			UIManager.put("ProgressBar.font", fontResourceNew);
			UIManager.put("RadioButton.font", fontResourceNew);
			UIManager.put("RadioButtonMenuItem.font", fontResourceNew);
			UIManager.put("ScrollPane.font", fontResourceNew);
			UIManager.put("TabbedPane.font", fontResourceNew);
			UIManager.put("TableHeader.font", fontResourceNew);
			UIManager.put("TextArea.font", fontResourceNew);
			UIManager.put("TextField.font", fontResourceNew);
			UIManager.put("TextPane.font", fontResourceNew);
			UIManager.put("TitledBorder.font", fontResourceNew);
			UIManager.put("ToggleButton.font", fontResourceNew);
			UIManager.put("ToolBar.font", fontResourceNew);
			UIManager.put("ToolTip.font", fontResourceNew);
			UIManager.put("Tree.font", fontResourceNew);
			UIManager.put("Viewport.font", fontResourceNew);
			
		}
		catch (Exception e){}
	}
	
//	******************************************************************************
	
	/** Sets the Model.
	 *  @param mdl The Model to be set.
	 */
	public void setModel(StepPostp stepPostp) {
		this.stepPostp = stepPostp;
		parser = new ParserHalfEdge(stepPostp);
		this.halfEdgeModelList = parser.getHalfEdgeList();
		if(this.halfEdgeModelList!=null){
			((PostpController)this.view.getController()).setModel(this.halfEdgeModelList);     
		}
		((PostpController)this.view.getController()).setView(this.view);
		((PostpView)this.view).getDrawingArea().setRightClickedCommand(new PopUpCommand(this));
		((PostpView)this.view).getDrawingArea().setClickedCommand(new SelectCommand(this));
		((PostpView)this.view).getDrawingArea().setZoom(((PostpViewState)this.view.getViewState()).getLimits());
		((PostpView)this.view).getDrawingArea().setPrecision(((PostpViewState)this.view.getViewState()).getPrecision());
		((PostpView)this.view).getDrawingArea().setSnap(false);
		((PostpView)this.view).getDrawingArea().setGridColor(((PostpViewState)this.view.getViewState()).gridColor);
		((PostpView)this.view).getDrawingArea().setGrid(((ViewState)this.view.getViewState()).isGridOn());
		((PostpView)this.view).getDrawingArea().setGrid(false);
		((PostpView)this.view).getDrawingArea().setGridIncs(((PostpViewState)this.view.getViewState()).getGridXInc(),((PostpViewState)this.view.getViewState()).getGridYInc());
		((PostpView)this.view).getDrawingArea().setBackground(((PostpViewState)this.view.getViewState()).bgcolor);
		this.getView().getViewState().setDistort(false);
    	this.getView().getDrawingArea().setDistort(false);
		this.view.getController().compose();
		this.view.getController().fit();
	}
	
	public synchronized void setStep(StepPostp stepPostp){
		parser = new ParserHalfEdge((StepPostp)stepPostp);
		this.stepPostp = (StepPostp)stepPostp;
		this.halfEdgeModelList = parser.getHalfEdgeList();
		((PostpController)this.view.getController()).setModel(this.halfEdgeModelList);     
		((PostpView)this.view).getDrawingArea().setClickedCommand(new SelectCommand(this));
		((PostpView)this.view).getDrawingArea().setRightClickedCommand(new PopUpCommand(this));
		this.getView().getViewState().setDistort(false);
    	this.getView().getDrawingArea().setDistort(false);
		this.view.getController().compose();
		this.view.getDrawingArea().repaint();
	}
	
	/** Returns the properties.
	 *@return The properties.
	 */
	public InsaneProperties getProperties() {
		return properties;
	}
	
	/** Returns the current controller.
	 *  @return The current controller.
	 */
	public IView getView() {
		return this.view;
	}
	
	//** Sets the initial Interface. */
	public void setInitialInterface() {
		((PostpViewState)this.view.getViewState()).setDistort(true);
		(this.view).getDrawingArea().setDistort(true);
		((PostpView)this.view).getDrawingArea().setRepainting(true);
		((PostpView)this.view).getDrawingArea().repaint();
		drawArea.removeAll();
		drawArea.add(((PostpView)this.view).getDrawingArea(), BorderLayout.CENTER);
		((PostpView)this.view).getDrawingArea().removeAllCommands();
		((PostpView)this.view).getDrawingArea().setCursor();
		((PostpView)this.view).getDrawingArea().setClickedCommand(new SelectCommand(this));
		drawArea.repaint();
		drawArea.updateUI(); 
		this.repaint();
	}
	
//	*****************************************************************************
	
	/** Adds a Command to the undoList.
	 * @param cmd a the desired command
	 **/
	public void addToUndo(Command cmd) {
		
	}
	
//	*****************************************************************************
	
	/** Adds a Command to the redoList.
	 * @param cmd a the desired command
	 */
	public void addToRedo(Command cmd) {
		
	}
	
//	*****************************************************************************
	
	/** Disables the redo command.*/
	public void nothingToRedo() {
		
	}
	
//	*****************************************************************************
	
	/** Disables the undo command.*/
	public void nothingToUndo() {
		
	}
	
//	*****************************************************************************
	
	/**
	 * Sets the Status Bar coord text.
	 * @param x The first "X" coordinate.
	 * @param y The second "Y" coordinate.
	 */
	public void setCoord(String x, String y) {

	}
	
//	*****************************************************************************
	
	/**
	 * Sets the Status Bar message.
	 * @param str The text to be shown
	 */
	public void setMessage(String str) {
		//	this.messageField.setText(str);
	}
	
	/**
	 * Sets the number formater
	 */
	private void setUpFormat() {
		numberFormat = (DecimalFormat)NumberFormat.getNumberInstance(Locale.UK);
		numberFormat.setMaximumFractionDigits(0);
	}
	
//	*****************************************************************************
	
	/** Method which executes the desired action to each command.*/
	public void actionPerformed(ActionEvent evt) {
		CommandHolder obj = (CommandHolder)evt.getSource();
		obj.getCommand().execute();
	}
	
	
	/** Sets the StateButtons of this Interface. */
	public void setStateButtons() {

	}
	
	/**
	 * The method return the model.
	 * @return Returns The model.
	 */
	public StepPostp getModel() {
		return this.stepPostp;
	}
	
	/**
	 * The method return the postpModel.
	 * @return Returns The postpModel.
	 */
	public PostpModel getPostpModel() {
		return postpModel;
	}
	
	/**
	 * The method set the field postpModel from the parameter postpModel.
	 * @param postpModel The postpModel to set.
	 */
	public void setPostpModel(PostpModel postpModel) {
		this.postpModel = postpModel;
	}
	
	
	public DesktopPostp getDesktop() {
		return desktop;
	}
	
	public void setDesktop(DesktopPostp desktop) {
		this.desktop = desktop;
	}
	
	public void update(Observable arg0, Object arg1) {
		try{
			StepPostp step = (StepPostp)((FemModelToPostpModel)arg0).getStepPostp();
			this.setStep(step);
			this.postpModel.addStep(step);
			Thread.sleep(100);
		}catch (Exception e){
			System.out.println("InterfacePostp update error thread");
		}
	}
	
	class IntFrameListner implements InternalFrameListener {
		
		public void internalFrameOpened(InternalFrameEvent e) {
			
		}
		
		public void internalFrameClosing(InternalFrameEvent e) {
			
		}
		
		public void internalFrameClosed(InternalFrameEvent e) {
			
		}
		
		public void internalFrameIconified(InternalFrameEvent e) {
			
		}
		
		public void internalFrameDeiconified(InternalFrameEvent e) {
			
		}
		
		public void internalFrameActivated(InternalFrameEvent e) {
			desktop.setAxisCheckBoxes();
			Color c = new Color(238,238,238);
			desktop.getDesktop().setSelectedFrame(e.getInternalFrame());
			if(((PostpViewState)view.getViewState()).getSelectionViewState().isElementsSelected()){
				desktop.getElementSelectionButton().setBackground(Color.cyan);
			}else{
				desktop.getElementSelectionButton().setBackground(c);
			}
			
			if(((PostpViewState)view.getViewState()).getSelectionViewState().isGaussSelected()){
				desktop.getGaussSelectionButton().setBackground(Color.cyan);
			}else{
				desktop.getGaussSelectionButton().setBackground(c);
			}
			
			if(((PostpViewState)view.getViewState()).getSelectionViewState().isNodesSelected()){
				desktop.getNodalSelectionButton().setBackground(Color.cyan);
			}else{
				desktop.getNodalSelectionButton().setBackground(c);
			}
			
			if(((PostpViewState)view.getViewState()).isDistort()){
				desktop.getDistortButton().setBackground(Color.cyan);
			}else{
				desktop.getDistortButton().setBackground(c);
			}
			
		}
		
		public void internalFrameDeactivated(InternalFrameEvent e) {
			
		}
		
	}
	
//	*****************************************************************************
}//end of this class